home *** CD-ROM | disk | FTP | other *** search
- //////////
- //
- // File: ImageCompressionUtilities.c
- //
- // Contains: Image Compression Utilities.
- //
- // Written by: Peter Hoddie, Sean Allen, Chris Flick
- // Revised by: Tim Monroe
- //
- // Copyright: © 1998 by Apple Computer, Inc., all rights reserved.
- //
- // Change History (most recent first):
- //
- // <6> 03/17/00 rtm moved some things to ImageCompressionUtilities.h; made some changes for Carbon
- // <5> 02/25/00 rtm changed pascal keyword to PASCAL_RTN, for Windows compatibility
- // <4> 12/16/98 rtm removed orphaned prototype for compressTransparentRLEwithHitTesting
- // <3> 05/28/98 rtm added some typecasting to minimize MSDev compiler warnings
- // <2> 03/22/98 rtm made changes to RecompressPictureFileWithTransparency, as per Chris' fixes
- // <1> 03/27/98 rtm existing file
- //
- //////////
-
-
- //////////
- //
- // header files
- //
- //////////
-
- #ifndef __IMAGECOMPRESSIONUTILITIES__
- #include "ImageCompressionUtilities.h"
- #endif
-
-
- // PICT to compressed image conversion
-
- // Given a QuickDraw picture, extract QuickTime compressed image data and description, if any.
- //
- // It does this by creating a temporary CGrafPort, installing a QuickDraw bottleneck
- // routine for the StdPix call, and then drawing the picture. Since this routine will
- // be called whenever QuickTime compressed image data is encountered, it can
- // stash away any found compressed data and description. On DrawPicture's return, the
- // stashed data and description is retrieved and returned to the caller.
- //
- // Worth noting in this utility is definition of the extractPictRecord. This is a
- // structure consisting of a CGrafPort structure followed by fields for a handle to
- // image data and an ImageDescription. This layout allows ExtractCompressData to open
- // a CGrafPort using the embedded CGrafPort field, and set this as the current port.
- // Then, in the StdPix routine extractStdPix, the current port can be retrieved and
- // cast to a pointer to an extractPictRecord to get access to the other fields.
- //
-
- #if 0
- OSErr ExtractCompressData ( PicHandle thePict, Handle *dataOut, ImageDescriptionHandle *idh )
- {
- OSErr err = noErr;
- extractPictRecord state;
- CQDProcs procs;
- GrafPtr savePort;
- Rect bounds;
-
- if ( dataOut )
- *dataOut = nil;
- if ( idh )
- *idh = nil;
-
- GetPort( &savePort );
-
- OpenCPort( &state.tempPort );
- SetStdCProcs( &procs );
- procs.newProc1 = (UniversalProcPtr)NewStdPixProc(extractStdPix);
- state.tempPort.grafProcs = &procs;
-
- state.data = nil;
- state.idh = nil;
-
- MacSetPort( (GrafPtr)&state.tempPort );
- HidePen();
-
- bounds = (**thePict).picFrame;
- DrawPicture(thePict, &bounds);
-
- MacSetPort( savePort );
- CloseCPort( &state.tempPort );
-
- DisposeRoutineDescriptor( procs.newProc1 );
-
- *dataOut = state.data;
- *idh = state.idh;
-
- return err;
- }
- #endif
-
-
- PASCAL_RTN void extractStdPix ( PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags )
- {
- #if TARGET_OS_MAC
- #pragma unused(srcRect,matrix,mode,mask,matte,matteRect,flags)
- #endif
- extractPictRecord *state;
-
- GetPort( (GrafPtr *)&state );
-
- if ( state->idh == nil ) {
- ImageDescriptionHandle desc;
- Ptr data;
- long bufferSize;
-
- if ( GetCompressedPixMapInfo(src, &desc, &data, &bufferSize, nil, nil) == noErr ) {
- state->idh = desc;
- HandToHand( (Handle *)&state->idh );
- PtrToHand( data, &state->data, bufferSize );
- }
- }
- }
-
-
- static ImageDescriptionHandle createImageDescription ( CodecType cType, PixMapHandle pixmap )
- {
- ImageDescriptionHandle desc = nil;
-
- if ( ( desc = (ImageDescription **)NewHandleClear(sizeof(ImageDescription)) ) != nil ) {
- ImageDescription *dp = *desc;
- Rect bounds = (**pixmap).bounds;
-
- dp->idSize = sizeof(ImageDescription);
- dp->cType = cType;
- dp->spatialQuality = codecNormalQuality;
- dp->width = bounds.right - bounds.left;
- dp->height = bounds.bottom - bounds.top;
- dp->hRes = 72L << 16;
- dp->vRes = 72L << 16;
- dp->dataSize = ((**pixmap).rowBytes & 0x3fff) * dp->height;
- dp->depth = (**pixmap).pixelSize;
- dp->clutID = -1;
-
- if ( SetImageDescriptionCTable( desc, (**pixmap).pmTable ) ) {
- DisposeHandle( (Handle) desc );
- desc = nil;
- }
- }
- return desc;
- }
-
- PASCAL_RTN void noDitherBitsProc (BitMap *srcBits, Rect *srcRect, Rect *dstRect, short mode, RgnHandle maskRgn)
- {
- mode &= ~ditherCopy;
- StdBits(srcBits, srcRect, dstRect, mode, maskRgn);
- }
-
- // DrawPictureNoDither is used to draw a QuickDraw picture but to turn convert any
- // use of ditherCopy graphics modes to graphics modes that don't use ditherCopy. It
- // only performs this with the stdbits bottleneck routine. Since ditherCopy is simply
- // ORed in with other graphics modes, the replaced bottleneck routine only needs to
- // AND off the ditherCopy flag.
-
- void DrawPictureNoDither(PicHandle pic, const Rect *bounds)
- {
- CQDProcs procs;
- GrafPtr savePort;
- CQDProcsPtr saveProcs;
-
- GetPort(&savePort);
- saveProcs = GetPortGrafProcs(savePort);
- SetStdCProcs( &procs );
-
- procs.bitsProc = NewQDBitsUPP(noDitherBitsProc);
-
- SetPortGrafProcs((CGrafPtr)savePort, &procs);
-
- DrawPicture(pic, bounds);
-
- SetPortGrafProcs((CGrafPtr)savePort, saveProcs);
-
- DisposeQDBitsUPP( procs.bitsProc );
- }
-
-
- //
- // The following is a routine that can be used to clean up the colors in a picture
- // before being compressed with the Animation compressor in 16-bits at codecNormal
- // quality. The QuickTime Animation compressor can operate in both a lossless and
- // lossy manner. This routine is meant to help when compressing in a lossy manner.
- //
- // By clean up, what's meant is the forcing of any colors that are sufficiently close
- // to white to colors that are not as close. Since the Animation compressor will
- // perform threshholding of the image's colors when codecNormal quality is specified,
- // without this preprocessing, colors very close to white can be mapped to white
- // in the compression. If white was chosen as the key color, pixels that are
- // close to white could possibly become transparent as well.
- //
- // While not used by other routines in this file, prepareFor16BitCompress is provided
- // as an example of how this might be done.
- //
- // Note that with codecLossless quality, there is no remapping of colors so this
- // step is unnecessary.
- //
-
- OSErr prepareFor16BitCompress(PicHandle *pic)
- {
- PicHandle newPicture = nil;
- Rect r;
- GWorldPtr gw = nil;
- CGrafPtr savePort;
- GDHandle saveGD;
- short rowBytes;
- Ptr baseAddr;
- long w, h;
- PixMapHandle pm;
- OSErr err = noErr;
-
- GetGWorld(&savePort, &saveGD);
-
- r = (***pic).picFrame;
- MacOffsetRect(&r, (short)-r.left, (short)-r.top);
-
- err = NewGWorld(&gw, 32, &r, nil, nil, useTempMem);
- if (err) {
- err = NewGWorld(&gw, 32, &r, nil, nil, 0);
- if (err) goto bail;
- }
-
- pm = GetGWorldPixMap(gw);
- LockPixels(pm);
- SetGWorld(gw, nil);
- EraseRect(&r);
-
- DrawPicture(*pic, &r);
-
- baseAddr = GetPixBaseAddr(pm);
- rowBytes = (**pm).rowBytes & 0x3fff;
- for (h=0; h<r.bottom; h++) {
- long *pixelPtr = (long *)baseAddr;
-
- for (w=0; w<r.right; w++, pixelPtr++) {
- UInt8 r, g, b, a;
- long pixel = *pixelPtr;
-
- if ((pixel & 0x0ffffff) == 0x00ffffff) // pure white
- continue;
-
- a = (pixel >> 24) & 0x0ff;
- r = (pixel >> 16) & 0x0ff;
- g = (pixel >> 8) & 0x0ff;
- b = (pixel >> 0) & 0x0ff;
- if ((r > kThreshold) && (g > kThreshold) && (b > kThreshold)) {
- r = g = b = kThreshold;
- *pixelPtr = (a << 24) | (kThreshold << 16) | (kThreshold << 8) | (kThreshold << 0);
- }
- }
-
- baseAddr += rowBytes;
- }
-
- newPicture = OpenPicture(&r);
- CopyBits((BitMapPtr)*GetGWorldPixMap(gw),
- (BitMapPtr)*GetGWorldPixMap(gw),
- &r,
- &r,
- ditherCopy,
- NULL);
-
- ClosePicture();
- UnlockPixels(pm);
-
- bail:
- if (gw)
- DisposeGWorld(gw);
-
- if (err == noErr) {
- if (newPicture) {
- KillPicture(*pic);
- *pic = newPicture;
- }
- }
-
- SetGWorld(savePort, saveGD);
-
- return err;
- }
-
-
- /*
- ---------------- Callback based routines for compressing with hittesting and transparency ----------------
- */
-
- /*
- RecompressWithTransparencyFromProc
-
- This is a routine either called indirectly through RecompressCompressedImageWithTransparency,
- RecompressPictureWithTransparency, or RecompressPictureFileWithTransparency or called directly.
- It takes a callback procedure which is responsible for returning the dimensions of the
- area of some type of drawable entity and for actually drawing that entity.
-
- includeHitTesting TRUE if hit testing data should be added to the compressed data
- keyColor A RGBColor that should be used as the transparency color. Pass nil
- if the image doesn't have transparent portions.
- hitTestRegion A RgnHandle specifying an area that is to be used as the hit test
- area. If you pass this, you must also set includeHitTesting to TRUE.
- This is optional as the callback procedure can perform drawing
- itself of the hit test area which is often suitable when both the
- image and hit test area were painted in a drawing program.
- idh Returned ImageDescriptionHandle for the compressed image data
- imageData Returned Handle to the compressed image data
-
- */
-
- OSErr RecompressWithTransparencyFromProc( CompressDrawProc drawProc, void * drawProcRefcon,
- Boolean includeHitTesting,
- RGBColor *keyColor,
- RgnHandle hitTestRegion,
- ImageDescriptionHandle *idh, Handle * imageData )
- {
- OSErr err = noErr;
- Rect bounds;
- CGrafPtr savePort;
- GDHandle saveDevice;
- GWorldPtr gwImage = nil; // always used
- GWorldPtr gwPrev = nil; // used if compressing with transparency (via keycolor)
- GWorldPtr gwMap = nil; // used if compressing with hittesting data
- ImageDescriptionHandle desc = nil; // resulting image description
- ImageDescriptionHandle gwMapDesc = nil;
- ImageSequence seq = 0; // compress sequence
- ImageSequenceDataSource mapSource = 0L;
- Ptr data = nil;
- long dataSize;
- UInt8 similarity;
- Boolean includeTransparency = false;
- RGBColor saveBackColor;
-
- GetGWorld( &savePort, &saveDevice );
-
- if( !drawProc || !idh || !imageData ){
- err = paramErr;
- goto bail;
- }
-
- // tell callback that it should initialize any storage it needs
- err = drawProc( kRecoProcInitMsg, nil, nil, 0, drawProcRefcon );
- if(err) goto bail;
-
- // determine bounds to use for compression
- err = drawProc( kRecoProcGetBoundsMsg, &bounds, nil, 0, drawProcRefcon );
- if(err) goto bail;
-
- err = QTNewGWorld(&gwImage, kCompressDepth, &bounds, nil, nil, kICMTempThenAppMemory);
- if(err) goto bail;
-
- if( keyColor ) {
- includeTransparency = true;
- }
-
- // Include hit testing? If so, we need a previous buffer and an 8-bit GWorld for the mask data
- if( includeHitTesting ) {
- err = QTNewGWorld(&gwPrev, kCompressDepth, &bounds, nil, nil, kICMTempThenAppMemory);
- if(err) goto bail;
-
- err = QTNewGWorld(&gwMap, 8, &bounds, nil, nil, kICMTempThenAppMemory);
- if(err) goto bail;
- }
-
- LockPixels( GetGWorldPixMap(gwImage) );
-
- if( gwPrev )
- LockPixels( GetGWorldPixMap(gwPrev) );
-
- if( gwMap )
- LockPixels( GetGWorldPixMap(gwMap) );
-
- if(gwPrev) {
- SetGWorld( gwPrev, nil );
- ClipRect( &bounds );
-
- GetBackColor( &saveBackColor );
- if( keyColor )
- RGBBackColor( keyColor );
-
- EraseRect( &bounds );
-
- RGBBackColor( &saveBackColor );
- }
-
- if( gwMap ) {
- SetGWorld( gwMap, nil );
-
- EraseRect( &bounds ); // paint background white
-
- err = drawProc( kRecoProcDrawMsg, &bounds, gwMap, kRecoProcHitTestingImageType, drawProcRefcon );
- if(err) goto bail;
-
- if( hitTestRegion ) {
- RGBColor blackRGB;
-
- blackRGB.red = blackRGB.green = blackRGB.blue = 0;
-
- RGBForeColor( &blackRGB );
- MacPaintRgn( hitTestRegion );
- }
-
- gwMapDesc = createImageDescription(kRawCodecType, GetGWorldPixMap(gwMap));
- err = MemError();
- if(err) goto bail;
- }
-
- SetGWorld( gwImage, nil );
- ClipRect( &bounds );
- EraseRect( &bounds );
-
- desc = (ImageDescriptionHandle) NewHandle(sizeof(ImageDescription));
-
-
- // NOTE: We pass codecLosslessQuality so that the key color if any is matched exactly. This avoids colors within
- // some threshhold different from the key color being taken as equivalent to the key color. Alternatively, we
- // could perform some threshhold processing on the source image's pixels and pass codecNormalQuality.
- if( includeHitTesting ) {
- // Allocate a compression sequence and add source data for hittest mask
- err = CompressSequenceBegin(&seq, GetGWorldPixMap(gwPrev), nil, nil, nil, kCompressDepth, kAnimationCodecType,
- anyCodec, codecLosslessQuality, codecLosslessQuality, 2, nil, 0, desc);
-
- // with hit testing, we have to add a data source to hold the mask data
- err = CDSequenceNewDataSource(seq, &mapSource, kRecoProcHitTestingImageType, 1, (Handle)gwMapDesc, nil, nil);
- if (err) goto bail;
-
- err = CDSequenceSetSourceData(mapSource, GetPixBaseAddr(GetGWorldPixMap(gwMap)), (**gwMapDesc).dataSize);
- if (err) goto bail;
-
- // What's the maximum size the compressed data could be--including hit-test data?
- err = GetCSequenceMaxCompressionSize(seq, GetGWorldPixMap(gwPrev), &dataSize);
- }
- else
- { // not hit-testing so we only need the image buffer
- err = CompressSequenceBegin( &seq, GetGWorldPixMap(gwImage), nil, &bounds, nil, kCompressDepth, kAnimationCodecType, 0,
- codecLosslessQuality, codecLosslessQuality, 2, nil, 0, desc );
- if(err) goto bail;
-
- // What's the maximum size the compressed data could be?
- err = GetCSequenceMaxCompressionSize(seq, GetGWorldPixMap(gwImage), &dataSize);
- }
- if (err) goto bail;
-
-
- data = NewPtr( dataSize );
- if( (err = MemError()) != noErr) goto bail;
-
- if( includeHitTesting /* with or without transparency */ ) {
- // With hittesting, we use two buffers. Actually we don't have to but do so to show how it can be
- // done. Also, this code was based upon some older code that did.
-
-
- // compress the GWorld painted with the keyColor exclusively
- err = CompressSequenceFrame( seq, GetGWorldPixMap(gwPrev), nil, 0, data, &dataSize, &similarity, nil );
- if ( err ) goto bail;
-
- err = SetCSequencePrev(seq, GetGWorldPixMap(gwPrev), nil);
- if (err) goto bail;
-
- // draw the image into the GWorld over area painted with keyColor so that if picture is transparent already
- // areas it doesn't paint will be in the key color
- SetGWorld( gwImage, nil );
-
- GetBackColor( &saveBackColor );
- if( keyColor )
- RGBBackColor( keyColor );
-
- EraseRect( &bounds );
-
- RGBBackColor( &saveBackColor );
-
- err = drawProc( kRecoProcDrawMsg, &bounds, gwImage, kRecoProcOriginalImageType, drawProcRefcon );
- if(err) goto bail;
-
- // now compress the GWorld holding the image drawn on top of the keyColor
- err = CompressSequenceFrame(seq, GetGWorldPixMap(gwImage), nil, 0, data, &dataSize, &similarity, nil);
- if (err) goto bail;
-
- // At this point, data points to the image data for just the difference between the two (thus generating transparency)
- // Also, hit testing data is contained in the image data if it was specified.
- }
- else if( includeTransparency ) {
- // For transparency case without hittesting, we get by with only using a single buffer so we special case the
- // code here. This is also for clarity.
-
- // compress the GWorld painted with the keyColor exclusively
- err = CompressSequenceFrame( seq, GetGWorldPixMap(gwImage), nil, codecFlagUpdatePrevious, data, &dataSize, &similarity, nil );
- if ( err ) goto bail;
-
- // draw the image into the GWorld over area painted with keyColor so that if picture is transparent already
- // areas it doesn't paint will be in the key color
- SetGWorld( gwImage, nil );
-
- GetBackColor( &saveBackColor );
- if( keyColor )
- RGBBackColor( keyColor );
-
- EraseRect( &bounds );
-
- RGBBackColor( &saveBackColor );
-
- err = drawProc( kRecoProcDrawMsg, &bounds, gwImage, kRecoProcOriginalImageType, drawProcRefcon );
- if(err) goto bail;
-
- // now compress the GWorld holding the image drawn on top of the keyColor
- err = CompressSequenceFrame(seq, GetGWorldPixMap(gwImage), nil, codecFlagUpdatePrevious, data, &dataSize, &similarity, nil);
- if (err) goto bail;
-
- // At this point, data points to the image data for just the difference between the two (thus generating transparency)
- // Also, hit testing data is contained in the image data if it was specified.
- }
- else
- {
- SetGWorld( gwImage, nil );
-
- // draw the image into the GWorld
- err = drawProc( kRecoProcDrawMsg, &bounds, gwImage, kRecoProcOriginalImageType, drawProcRefcon );
- if(err) goto bail;
-
- // compress the GWorld containing the image painted on white
- err = CompressSequenceFrame( seq, GetGWorldPixMap(gwImage), nil, 0, data, &dataSize, &similarity, nil );
- if ( err ) goto bail;
-
- // At this point, data points to the image data for just the image, newly compressed. Also, hit testing data is contained
- // in the image data if it was specified.
- }
-
- CDSequenceEnd( seq );
- seq = 0;
-
- // free the GWorlds and drop references so we have more memory for PtrToHand
- if( gwImage ) DisposeGWorld( gwImage );
- gwImage = nil;
- if( gwMap ) DisposeGWorld( gwMap );
- gwMap = nil;
- if( gwPrev ) DisposeGWorld( gwPrev );
- gwPrev = nil;
-
- err = PtrToHand( data, imageData, dataSize );
- if ( err ) goto bail;
-
- *idh = desc;
- desc = nil; // forget about this name for ImageDescriptionHandle so dispose below doesn't catch it
-
- bail:
- // tell callback to dispose of anything it allocated. We pass 'err ' in portType if an error occurred
- drawProc( kRecoProcDisposeMsg, nil, nil, err ? FOUR_CHAR_CODE('err ') : 0, drawProcRefcon );
-
- CDSequenceEnd( seq );
- SetGWorld( savePort, saveDevice );
-
- if(gwImage) DisposeGWorld( gwImage );
- if(gwMap ) DisposeGWorld( gwMap );
- if(gwPrev ) DisposeGWorld( gwPrev );
- if(desc) DisposeHandle((Handle) desc );
- if(gwMapDesc) DisposeHandle((Handle) gwMapDesc );
- if(data) DisposePtr( data );
-
- return err;
- }
-
-
- /*
- myPictureCompressDrawProc
-
- Helper routine to be used with RecompressWithTransparencyFromProc to compress QuickDraw Pictures.
- */
-
- static PASCAL_RTN OSErr myPictureCompressDrawProc( short message, Rect * bounds, GWorldPtr drawingPort, OSType drawingImageType, void * refcon )
- {
- #if TARGET_OS_MAC
- #pragma unused(drawingPort)
- #endif
- OSErr err = noErr;
- PictureCompressProcData * data = refcon;
- Rect r;
-
- switch( message ) {
- case kRecoProcInitMsg:
- break;
-
- case kRecoProcDisposeMsg:
- break;
-
- case kRecoProcGetBoundsMsg:
- r = (**data->picture).picFrame;
-
- r.left = EndianS16_BtoN(r.left);
- r.top = EndianS16_BtoN(r.top);
- r.bottom = EndianS16_BtoN(r.bottom);
- r.right = EndianS16_BtoN(r.right);
-
- MacOffsetRect(&r, (short)-r.left, (short)-r.top );
-
- *bounds = r;
- break;
-
- case kRecoProcDrawMsg:
- r = (**data->picture).picFrame;
-
- r.left = EndianS16_BtoN(r.left);
- r.top = EndianS16_BtoN(r.top);
- r.bottom = EndianS16_BtoN(r.bottom);
- r.right = EndianS16_BtoN(r.right);
-
- MacOffsetRect( &r, (short)-r.left, (short)-r.top );
-
- if( kRecoProcOriginalImageType == drawingImageType )
- DrawPictureNoDither( data->picture, &r );
- break;
- default:
- err = -1;
- }
-
- return err;
- }
-
-
- /*
- myImageCompressDrawProc
-
- Helper routine to be used with RecompressWithTransparencyFromProc to compress QuickTime compressed image data.
- */
- static PASCAL_RTN OSErr myImageCompressDrawProc( short message, Rect * bounds, GWorldPtr drawingPort, OSType drawingImageType, void * refcon )
- {
- #if TARGET_OS_MAC
- #pragma unused(drawingImageType)
- #endif
-
- OSErr err = noErr;
- CompressedImageCompressProcData * data = refcon;
- Rect r;
-
- switch( message ) {
- case kRecoProcInitMsg:
- break;
- case kRecoProcDisposeMsg:
- break;
- case kRecoProcGetBoundsMsg:
- r.left = r.top = 0;
- r.right = (**data->imageDesc).width;
- r.bottom = (**data->imageDesc).height;
-
- *bounds = r;
- break;
- case kRecoProcDrawMsg:
- {
- SignedByte saveState;
-
- r.left = r.top = 0;
- r.right = (**data->imageDesc).width;
- r.bottom = (**data->imageDesc).height;
-
- saveState = HGetState( data->imageData );
- HLockHi( data->imageData );
-
- if( kRecoProcOriginalImageType == drawingImageType )
- err = DecompressImage( *data->imageData, data->imageDesc, GetGWorldPixMap(drawingPort), &r, &r, srcCopy, nil );
-
- HSetState( data->imageData, saveState );
- }
- break;
- default:
- err = -1;
- }
-
- return err;
- }
-
-
-
- /*
- RecompressCompressedImageWithTransparency
-
- Given an ImageDescriptionHandle and a handle to image data, generate new RLE compressed data
- with optional hitTesting and transparency.
- */
- OSErr RecompressCompressedImageWithTransparency( ImageDescriptionHandle originalDesc, Handle originalImageData,
- RGBColor *keyColor,
- RgnHandle hitTestRegion,
- ImageDescriptionHandle *idh, Handle * imageData )
- {
- OSErr err = noErr;
- CompressedImageCompressProcData params;
-
- params.imageDesc = originalDesc;
- params.imageData = originalImageData;
-
- err = RecompressWithTransparencyFromProc( myImageCompressDrawProc, ¶ms,
- (Boolean)(hitTestRegion != nil),
- keyColor,
- hitTestRegion,
- idh, imageData );
-
- return err;
- }
-
- /*
- RecompressPictureWithTransparency
-
- Given a QuickDraw PicHandle, generate new RLE compressed data with optional hitTesting and transparency.
- */
- OSErr RecompressPictureWithTransparency( PicHandle originalPicture,
- RGBColor *keyColor,
- RgnHandle hitTestRegion,
- ImageDescriptionHandle *idh, Handle * imageData )
- {
- OSErr err = noErr;
- PictureCompressProcData params;
-
- params.picture = originalPicture;
-
- err = RecompressWithTransparencyFromProc( myPictureCompressDrawProc, ¶ms,
- (Boolean)(hitTestRegion != nil),
- keyColor,
- hitTestRegion,
- idh, imageData );
-
- return err;
- }
-
- /*
- RecompressPictureFileWithTransparency
-
- Given a QuickDraw PICT file, generate new RLE compressed data with optional hitTesting and transparency.
- This function uses GetCompressedImageFromPicture to do the actual work on the PicHandle retrieved from
- the PICT file.
- */
- OSErr RecompressPictureFileWithTransparency( FSSpec * spec,
- RGBColor *keyColor,
- RgnHandle hitTestRegion,
- ImageDescriptionHandle *idh, Handle * imageData )
- {
- OSErr err = noErr;
- short sourceRefNum = 0;
- PicHandle picture = nil;
- long eof;
- long countBytes;
-
- *idh = nil;
- *imageData = nil;
-
- BailOSErr(FSpOpenDF( spec, fsRdPerm, &sourceRefNum ));
-
- BailOSErr(GetEOF( sourceRefNum, &eof ));
- eof -= 512;
-
- BailOSErr(SetFPos( sourceRefNum, fsFromStart, 512 ));
-
- picture = (PicHandle) NewHandle(eof);
- err = MemError();
- BailOSErr(err);
-
- countBytes = eof;
- HLock((Handle) picture);
- BailOSErr( FSRead( sourceRefNum, &countBytes, *picture) );
- HUnlock((Handle) picture);
-
- BailOSErr( RecompressPictureWithTransparency( picture, keyColor, hitTestRegion,
- idh, imageData ));
-
- bail:
- if ( picture ) DisposeHandle((Handle) picture );
- if ( sourceRefNum ) FSClose( sourceRefNum );
-
- return err;
- }
-
-